@startuml
class MainProcess {
	+MainProcess()
	+void run
}

class MainWindow {
    +MainWindow(config& config, QWidget *parent = nullptr)
    +~MainWindow()
    +void closeEvent(QCloseEvent *event)
    +void setUser(const user& user)
    +void on_saveButton_clicked()
    +void addDataToSecureDataMap(const SecureDataMapItem& item)
    +void openAccWindow()
    +void showClearedPopup()
    +void on_totpButton_clicked()
    +void addTOTP(const TOTP& totp)
    +void deleteTOTP(const TOTP& totp)
    +void showContextMenu(const QPoint &pos)
    +void trayIconActivated(QSystemTrayIcon::ActivationReason reason)
    +void openTotp()
    +void fillTable()
    +void createContextMenu()
    +void copyPassword()
    +void deleteRow()
    +void createTrayIcon()

    -QSystemTrayIcon *trayIcon
    -QMenu *trayIconMenu
    -QMenu *tableContextMenu
    -QAction *copyPasswordAction
    -QAction *deleteRowAction
    -QAction *minimizeAction
    -QAction *restoreAction
    -QAction *quitAction
    -QAction *openTotpAction
    -Ui::MainWindow *ui
    -std::unique_ptr<SecureDataMap> _sdm
    -std::unique_ptr<cryptomanager> _manag
    -std::unique_ptr<TOTPManager> _totpManager
    -config& _config
    -PopUp *_popup
    -user _user
    -ClipboardWatcher _clipboard_watcher
    -bool _data_clicked
    -accountDataDialog *_dataDialog
    -TOTPWindow *_totpDialog
}

class ClipboardWatcher {
    -QTimer timer
    -QString clipboardHash

    +ClipboardWatcher(QObject *parent = nullptr)
    +void setClipboardData(const QString &data)
    +void startTimer()
    +void clipboardCleared() : signal
    -QString generateHash(const QString &data)
    +bool eventFilter(QObject *obj, QEvent *event)
    -void clearClipboard()
}

enum DataType {
    SERVICE_NAME
    LOGIN
    PASSWORD
    NOTES
}

class accountDataDialog {
    -QLineEdit* _serviceNameEdit
    -QLineEdit* _loginEdit
    -QLineEdit* _passwordEdit
    -QPlainTextEdit* _secureNoteEdit
    -QLabel* _serviceNameLabel
    -QLabel* _loginLabel
    -QLabel* _passwordLabel
    -QLabel* _secureNoteLabel
    -QLabel* _passwordWarning
    -QPushButton* _generatePasswordButton
    -QDialogButtonBox* _buttonBox
    -std::shared_ptr<cipherManager> _manager
    -std::shared_ptr<SecureDataMapItem> _item
    -PopUp* _pop_up
    -ClipboardWatcher& _clipboard_watcher

    +accountDataDialog(ClipboardWatcher& clipboard_watcher, QWidget *parent = nullptr, const std::shared_ptr<cipherManager>& manager = nullptr)
    +accountDataDialog(ClipboardWatcher& clipboard_watcher, QWidget *parent = nullptr, SecureDataMapItem* account = nullptr)
    +void sendData(const SecureDataMapItem &user)
    +void sendDataCopied()
    +void showPass()
    +void updateData()
    +void createData()
    +void generatePassword()
    +void isPasswordSecure(const QString& password)
    +bool eventFilter(QObject *obj, QEvent *event)
    -bool checkLineEditsNonEmpty()
}

class config {
    -std::filesystem::path appDir
    -std::filesystem::path usersFile
    -std::filesystem::path pathToUsersSecrets
    +config(const std::string& currentAppFile)
    +void setUsersFiles(const std::filesystem::path& path)
    +void setPathToUsersSecrets(const std::filesystem::path& path)
    +void saveConfig()
    +std::filesystem::path getUsersFile() const
    +std::filesystem::path getPathToUsersSecrets() const
}

class PopUp {
    -QLabel label
    -QGridLayout layout
    -QPropertyAnimation animation
    -float popupOpacity
    -QTimer *timer
    -QRect currentGeometry
    +PopUp(QRect currentGeometry, QWidget *parent = 0)
    +void paintEvent(QPaintEvent *event)
    +void setPopupText(const QString& text)
    +void show()
    +slot void hideAnimation()
    +slot void hide()
    +void setPopupOpacity(float opacity)
    +float getPopupOpacity() const
}

'модуль входа и регистрации
class LoginDialog {
    -QLabel *labelUsername
    -QLabel *labelPassword
    -QLabel *labelUserCorrect
    -QComboBox *comboUsername
    -QLineEdit *editPassword
    -QDialogButtonBox *buttons
    -QPushButton *addUserButton
    -QPushButton *closeButton
    -usersList& list
    +LoginDialog(usersList &list, QWidget *parent = nullptr)
    +void setUsername(QString &username)
    +void setPassword(QString &password)
    +void setUpGUI()
    +void slotAcceptLogin()
    +void addUser()
    +signal void acceptLogin(const user& user)
}

class registrationDialog {
    -QLabel *labelUsername
    -QLabel *labelPassword
    -QLabel *label2ndPassword
    -QLabel *labelUserCorrect
    -QLabel *passwordErrorLabel
    -QLineEdit *editPassword
    -QLineEdit *edit2ndPassword
    -QLineEdit *editUserName
    -QDialogButtonBox *buttons
    -QComboBox *algorithmCombo
    -bool passwordsAreSame
    -bool passwordIsSecure
    -PopUp *_pop_up
    +registrationDialog(QWidget *parent = nullptr)
    +void checkPasswords()
    +void createUser()
    +void isPasswordSecure(const QString& password)
    +void generatePassword()
    +void setUpGUI()
    +signal void sendUser(const user& user)
    +signal void sendDataCopied()
}
'конец модуля входа и регистрации


class user {
    -std::string _login
    -std::string _salt
    -CipherAlgorithm _cipher_algorithm_
    -Botan::secure_vector<std::uint8_t> _hashedPassword
    -std::filesystem::path _dataPath
    -std::filesystem::path _totpPath
    +user()
    +user(const std::string& line)
    +void setLogin(const std::string& login)
    +void setSalt(const std::string& salt)
    +void setHashedPassword(const std::string& hashedPassword)
    +void setHashedPassword(const Botan::secure_vector<uint8_t>& hashedPassword)
    +void setDataPath(const std::string& path)
    +void setTotpPath(const std::string& path)
    +void setAlgorithm(const CipherAlgorithm& algos = CipherAlgorithm::Kuznyechik_CBC)
    +std::string getLogin() const
    +std::string getSalt() const
    +std::filesystem::path getDataPath() const
    +std::filesystem::path getTotpPath() const
    +CipherAlgorithm getAlgorithm() const
    +bool compare_hashes(const Botan::secure_vector<uint8_t>& hash1) const
    +Botan::SymmetricKey generatePass() const
    -std::string getHash() const
    +friend std::string to_string(const user& user)
}

class usersList {
    -std::vector<user> _users
    +usersList(const std::filesystem::path& path, QObject *parent = nullptr)
    +iterator begin()
    +iterator end()
    +const_iterator begin() const
    +const_iterator end() const
    +user& operator[](int index)
    +void saveInFile(const std::filesystem::path& path)
    +bool empty() const
    +slot void appendUser(const user& user)
}


'модуль криптографии
enum CipherAlgorithm {
    Kuznyechik_CBC
    Magma_CBC
    AES_256_CBC
}


class Cipher {
    -std::unique_ptr<Botan::RandomNumberGenerator> rng
    -std::unique_ptr<Botan::Cipher_Mode> cipher
    -Botan::InitializationVector iv
    +Cipher()
    +bool chooseCipher(CipherAlgorithm algorithm, Botan::Cipher_Dir direction)
    +void setIV(const Botan::secure_vector<uint8_t>& iv)
    +void saveIVinFile(const std::string& filename) const
    +void saveIVInByteArray(Botan::secure_vector<uint8_t>& data) const
    +bool loadIV(const std::string& filename, std::size_t ivSize)
    +void generateIvWithSaving(std::size_t size)
    +Botan::InitializationVector generateIV(std::size_t size)
    +Botan::secure_vector<uint8_t> encrypt(const Botan::SymmetricKey& key, const Botan::secure_vector<uint8_t>& plaintext) const
    +Botan::secure_vector<uint8_t> decrypt(const Botan::SymmetricKey& key, const Botan::secure_vector<uint8_t>& ciphertext) const
    +Botan::secure_vector<uint8_t> updateEncryption(const Botan::SymmetricKey& key, const Botan::InitializationVector& newIV,
                                                   const Botan::secure_vector<uint8_t>& plaintext, CipherAlgorithm algorithm = CipherAlgorithm::Kuznyechik_CBC)
}

class cipherManager {
    -std::shared_ptr<Cipher> _cipher
    -Botan::SymmetricKey key
    -Botan::Cipher_Dir direction
    -CipherAlgorithm algos
    -Botan::secure_vector<uint8_t> path
    +cipherManager(CipherAlgorithm algorithm, Botan::SymmetricKey key, std::filesystem::path fileNameIV)
    +cipherManager(CipherAlgorithm algorithm, Botan::SymmetricKey key, const Botan::secure_vector<uint8_t>& iv)
    +~cipherManager()
    +void setPath(std::filesystem::path fileNameIV)
    +void setPath(Botan::secure_vector<uint8_t> fileNameIV)
    +Botan::secure_vector<uint8_t> encrypt(const Botan::secure_vector<uint8_t> &plaintext, bool saveIV)
    +Botan::secure_vector<uint8_t> decrypt(const Botan::secure_vector<uint8_t> &plaintext, bool saveIV)
    +Botan::secure_vector<uint8_t> updateDecryption(const Botan::InitializationVector& newIV, const Botan::secure_vector<uint8_t> &plaintext)
    +std::shared_ptr<Cipher> getCipher()
    +Botan::InitializationVector generateIV()
}


class cryptomanager {
    -cipherManager manager
    -std::fstream file
    -CipherAlgorithm algorithm
    -Botan::SymmetricKey key
    -std::filesystem::path path
    +cryptomanager(const std::filesystem::path& path, CipherAlgorithm algorithm, Botan::SymmetricKey key)
    +SecureDataMap getData()
    +void WriteData(SecureDataMap& map)
    +~cryptomanager()
}

class SecureDataMap {
    -std::vector<SecureDataMapItem> data
    -std::shared_ptr<cipherManager> manager
    +SecureDataMap(std::shared_ptr<cipherManager> manager)
    +SecureDataMap(const SecureDataMap& map) = default
    +void addItemBySecureDataItem(SecureDataMapItem&& item)
    +void addItemBySecureDataItem(const SecureDataMapItem& item)
    +void addItemByStrings(std::string service, std::string login, std::string unecryptedPassword, std::string unecryptedData)
    +std::vector<SecureDataMapItem>::const_iterator getData(const std::string& login) const
    +std::vector<SecureDataMapItem>::iterator getDataViaLoginAndServiceName(const std::string &login, const std::string &service)
    +void clearData()
    +std::size_t count() const
    +void deleteItemByLogin(std::string login)
    +void deleteItem(std::vector<SecureDataMapItem>::const_iterator iter)
    +std::vector<SecureDataMapItem>::iterator begin()
    +std::vector<SecureDataMapItem>::iterator end()
    +std::vector<SecureDataMapItem>::const_iterator begin() const
    +std::vector<SecureDataMapItem>::const_iterator end() const
    +std::shared_ptr<cipherManager> getCipherManager() const
    +Botan::secure_vector<uint8_t> writeMapInSecureVector()
}


class SecureDataMapItem {
    -QString _service_name
    -QString _login
    -Botan::secure_vector<uint8_t> _password
    -Botan::secure_vector<uint8_t> _notes
    -std::weak_ptr<cipherManager> _manager
    -bool _isEmpty
    +SecureDataMapItem()
    +SecureDataMapItem(QString service_name, QString login, Botan::secure_vector<uint8_t> password, Botan::secure_vector<uint8_t> notes, std::weak_ptr<cipherManager> manager)
    +SecureDataMapItem(std::string service_name, std::string login, Botan::secure_vector<uint8_t> password, Botan::secure_vector<uint8_t> notes, std::weak_ptr<cipherManager> manager)
    +SecureDataMapItem(const std::string& data, std::weak_ptr<cipherManager> manager)
    +SecureDataMapItem(const SecureDataMapItem& item)
    +QString getDecryptedData(DataType type) const
    +std::string getEncryptedData(DataType type) const
    +void setDecryptedData(DataType type, const QString& el)
    +void setEncryptedData(DataType type, const Botan::secure_vector<uint8_t>& el)
    +void setManager(std::weak_ptr<cipherManager> manager)
    +void clear()
    +void reDecryptData(const Botan::InitializationVector& newIv)
    +bool empty() const
}
'конец модуля криптографии

'модуль totp
class TOTPManager {
    -QString filepath
    -Botan::SymmetricKey encryptionKey
    -std::vector<TOTP> totps
    -std::string algos
    +TOTPManager(const std::filesystem::path& filepath, CipherAlgorithm algorithm, const Botan::SymmetricKey& encryptionKey, QObject* parent = nullptr)
    +const std::vector<TOTP>& getTOTPs() const
    +void saveTOTPs()
    +void loadTOTPs()
    +void addTOTP(const TOTP& totp)
    +void deleteTOTP(const TOTP& totp)
    -QByteArray encrypt(const QByteArray& plaintext)
    -QByteArray decrypt(const QByteArray& ciphertext)
}


class TOTP {
    -QString label
    -Botan::SymmetricKey key
    -QString algorithm
    -int digits
    -int period
    +std::chrono::system_clock::time_point creation_time
    +TOTP(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
    +QString getLabel() const
    +Botan::SymmetricKey getKey() const
    +QString getAlgorithm() const
    +int getDigits() const
    +int getPeriod() const
}

class ClickableLabel {
    +ClickableLabel(QWidget *parent = nullptr)
    +void mousePressEvent(QMouseEvent *event)
    +signal void clicked()
}

class TOTPItemWidget {
    -TOTP m_totp
    -QProgressBar *progressBar
    -ClickableLabel *passwordLabel
    -QTimer *timer
    +TOTPItemWidget(const TOTP& totp, QWidget *parent = nullptr)
    +TOTP getTOTP() const
    +void updateProgress()
    +QString getPasswrodLabel()
    +signal void passwordCopied(QString)
    +signal void deleteRequested(const TOTP&)
    +slot void sendCopySignal()
    +slot void onDeleteClicked()
}

class TOTPConfigWindow {
    -QLineEdit *keyInput
    -QComboBox *algorithmCombo
    -QComboBox *digitsCombo
    -QLineEdit *periodInput
    -QLineEdit *nameInput
    +TOTPConfigWindow(QWidget *parent = nullptr)
    +signal void configSaved(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
    +slot void saveConfig()
}

class TOTPListWidget {
    -QListWidget *totpListWidget
    -ClipboardWatcher &_clipboard_watcher
    +TOTPListWidget(ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
    +void addTOTP(const TOTP& totp)
    +slot void copyTOTPToClipboard(QListWidgetItem *item)
    +slot void copyTOTPToClipboard(QString password)
    +slot void onTOTPDeleteRequested(const TOTP &totp)
    +signal void PasswordCopied()
    +signal void totpDeleted(const TOTP&)
}

class TOTPWindow {
    -TOTPListWidget *totpListWindow
    -PopUp *popup
    -ClipboardWatcher &_clipboard_wather
    +TOTPWindow(ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
    +TOTPWindow(const std::vector<TOTP>& totps, ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
    +signal void addedTotp(const TOTP&)
    +signal void deleteTotp(const TOTP&)
    +slot void addTOTP()
    +slot void addTOTPToList(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
    +slot void openPopupWindow()
    +slot void fillTotpListWindow(const std::vector<TOTP>& totps)
    +slot void onTotpDeleted(const TOTP& totp)
}
'конец модуля totp


'Главный процесс программы
usersList "1" *-- "0..*" user

MainProcess --> config
MainProcess --> usersList
MainProcess --> LoginDialog
MainProcess --> MainWindow


'Окно создание диалогов
LoginDialog --> registrationDialog
LoginDialog o-- usersList


'totp
TOTPManager o-- TOTP
TOTPManager --> CipherAlgorithm
TOTPWindow *-- TOTPListWidget
TOTPWindow *-- TOTPConfigWindow
TOTPListWidget *-- TOTPItemWidget
TOTPItemWidget *-- TOTP
TOTPItemWidget *-- ClickableLabel


'криптография
cipherManager --> Cipher
Cipher -> CipherAlgorithm
SecureDataMapItem ..> DataType
SecureDataMap "1" *-- "0..*" SecureDataMapItem
SecureDataMap "1" --> "1" cipherManager
cryptomanager --> cipherManager
cryptomanager --> CipherAlgorithm

'отображение данных
accountDataDialog ..> DataType
accountDataDialog o-- ClipboardWatcher
accountDataDialog --> SecureDataMapItem
accountDataDialog --> cipherManager

'главное окно
MainWindow *-- config
MainWindow *-- cryptomanager
MainWindow *-- SecureDataMap
MainWindow *-- TOTPManager
MainWindow *-- accountDataDialog
MainWindow *-- ClipboardWatcher
MainWindow *-- TOTPWindow
MainWindow *-- PopUp
MainWindow *-- user


@enduml
